use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::collections::HashMap;
use std::fmt;

/// 精确的温度类型，避免浮点精度问题
/// 专门为 LLM API 设计，确保序列化时的精度控制
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct Temperature(f32);

impl Temperature {
    /// 创建新的温度值，自动舍入到一位小数
    pub fn new(value: f32) -> Self {
        // 舍入到一位小数，避免浮点精度问题
        let rounded = (value * 10.0).round() / 10.0;
        Temperature(rounded)
    }

    /// 获取温度值
    pub fn value(&self) -> f32 {
        self.0
    }

    /// 常用的温度预设
    pub const DETERMINISTIC: Temperature = Temperature(0.0);
    pub const LOW: Temperature = Temperature(0.3);
    pub const BALANCED: Temperature = Temperature(0.7);
    pub const CREATIVE: Temperature = Temperature(1.0);
    pub const HIGH: Temperature = Temperature(1.5);
}

impl From<f32> for Temperature {
    fn from(value: f32) -> Self {
        Temperature::new(value)
    }
}

impl From<Temperature> for f32 {
    fn from(temp: Temperature) -> Self {
        temp.0
    }
}

impl Default for Temperature {
    fn default() -> Self {
        Temperature::BALANCED
    }
}

impl Serialize for Temperature {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        // 确保序列化时使用精确的值
        serializer.serialize_f32(self.0)
    }
}

impl<'de> Deserialize<'de> for Temperature {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let value = f32::deserialize(deserializer)?;
        Ok(Temperature::new(value))
    }
}

impl fmt::Display for Temperature {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{:.1}", self.0)
    }
}

/// Role enum representing the role of a message sender
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub enum Role {
    /// System message role
    System,
    /// User message role
    User,
    /// Assistant message role
    Assistant,
    /// Function message role
    Function,
    /// Custom role (for future extensions)
    Custom(String),
    /// Tool message role
    Tool,
}

impl Role {
    /// Create a new role
    pub fn new(role: impl Into<String>) -> Self {
        let role_str = role.into();
        match role_str.to_lowercase().as_str() {
            "system" => Role::System,
            "user" => Role::User,
            "assistant" => Role::Assistant,
            "function" => Role::Function,
            "tool" => Role::Tool,
            _ => Role::Custom(role_str),
        }
    }

    /// Convert Role to its string representation
    pub fn as_str(&self) -> &str {
        match self {
            Role::System => "system",
            Role::User => "user",
            Role::Assistant => "assistant",
            Role::Function => "function",
            Role::Tool => "tool",
            Role::Custom(s) => s.as_str(),
        }
    }
}

impl From<Role> for String {
    fn from(role: Role) -> Self {
        match role {
            Role::System => "system".to_string(),
            Role::User => "user".to_string(),
            Role::Assistant => "assistant".to_string(),
            Role::Function => "function".to_string(),
            Role::Tool => "tool".to_string(),
            Role::Custom(s) => s,
        }
    }
}

impl From<&str> for Role {
    fn from(s: &str) -> Self {
        Role::new(s)
    }
}

impl From<String> for Role {
    fn from(s: String) -> Self {
        Role::new(s)
    }
}

impl PartialEq<&str> for Role {
    fn eq(&self, other: &&str) -> bool {
        self.as_str() == *other
    }
}

impl fmt::Display for Role {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.as_str())
    }
}

impl Default for Role {
    fn default() -> Self {
        Self::User
    }
}

/// Represents a message in a conversation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Message {
    /// The role of the message sender (e.g., "user", "assistant", "system")
    pub role: Role,
    /// The content of the message
    pub content: String,
    /// Additional metadata for the message
    pub metadata: Option<HashMap<String, serde_json::Value>>,
    /// Optional name for the message, used in function calls
    pub name: Option<String>,
}

impl Message {
    /// Create a new message
    pub fn new(
        role: Role,
        content: String,
        metadata: Option<HashMap<String, serde_json::Value>>,
        name: Option<String>,
    ) -> Self {
        Self {
            role,
            content,
            metadata,
            name,
        }
    }

    /// Create a new message with a name
    pub fn with_name(mut self, name: &str) -> Self {
        self.name = Some(name.to_string());
        self
    }

    /// Add metadata to the message
    pub fn with_metadata(mut self, key: &str, value: serde_json::Value) -> Self {
        let metadata = self.metadata.get_or_insert_with(HashMap::new);
        metadata.insert(key.to_string(), value);
        self
    }
}

/// Options for LLM text generation
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LlmOptions {
    /// Temperature parameter for controlling randomness (0.0-1.0) - 使用精确的 Temperature 类型
    pub temperature: Option<Temperature>,
    /// Maximum number of tokens to generate
    pub max_tokens: Option<u32>,
    /// Whether to stream the output
    pub stream: bool,
    /// Stop sequences that end generation
    pub stop: Option<Vec<String>>,
    /// Model name
    pub model: Option<String>,
    /// Additional model-specific parameters
    #[serde(flatten)]
    pub extra: serde_json::Map<String, serde_json::Value>,
}

impl Default for LlmOptions {
    fn default() -> Self {
        Self {
            // 使用精确的 Temperature 类型，自动处理精度问题
            temperature: Some(Temperature::BALANCED),
            max_tokens: Some(1000),
            stream: false,
            stop: None,
            model: None,
            extra: serde_json::Map::new(),
        }
    }
}

impl LlmOptions {
    /// Create a new LLM options
    pub fn new() -> Self {
        Self::default()
    }

    /// Set temperature - 自动应用精度控制
    pub fn with_temperature(mut self, temperature: f32) -> Self {
        self.temperature = Some(Temperature::new(temperature));
        self
    }

    /// Set temperature using Temperature type
    pub fn with_temperature_precise(mut self, temperature: Temperature) -> Self {
        self.temperature = Some(temperature);
        self
    }

    /// Set maximum token count
    pub fn with_max_tokens(mut self, max_tokens: u32) -> Self {
        self.max_tokens = Some(max_tokens);
        self
    }

    /// Set whether to stream the output
    pub fn with_stream(mut self, stream: bool) -> Self {
        self.stream = stream;
        self
    }

    /// Set stop sequences
    pub fn with_stop(mut self, stop: Vec<String>) -> Self {
        self.stop = Some(stop);
        self
    }

    /// Set model name
    pub fn with_model(mut self, model: impl Into<String>) -> Self {
        self.model = Some(model.into());
        self
    }

    /// Add extra options
    pub fn with_extra(
        mut self,
        key: impl Into<String>,
        value: impl Into<serde_json::Value>,
    ) -> Self {
        self.extra.insert(key.into(), value.into());
        self
    }
}

/// Create system message
pub fn system_message(content: &str) -> Message {
    Message {
        role: Role::System,
        content: content.to_string(),
        metadata: None,
        name: None,
    }
}

/// Create user message
pub fn user_message(content: &str) -> Message {
    Message {
        role: Role::User,
        content: content.to_string(),
        metadata: None,
        name: None,
    }
}

/// Create assistant message
pub fn assistant_message(content: &str) -> Message {
    Message {
        role: Role::Assistant,
        content: content.to_string(),
        metadata: None,
        name: None,
    }
}

/// Create tool message
pub fn tool_message(content: &str) -> Message {
    Message {
        role: Role::Tool,
        content: content.to_string(),
        metadata: None,
        name: None,
    }
}
